#pragma once
#include <string>
#include <memory>
#include "Socket.hpp"
#include "Epoller.hpp"
#include "../logsystem/logger/log.h"
using namespace Net_Work;
using namespace EpollerModule;
const int gbacklog = 8;
const int gmaxnum = 32;
class EpollServer
{
public:
    EpollServer(int port) : _serverport(port), _stop(true), _epoller(new Epoller()), _listensock(new TcpSocket())
    {
    }

    void Init()
    {
        // 1.设置listen状态

        _listensock->BuildListenSocketMethod(_serverport, gbacklog);
        // 2.创建epoll
        _epoller->InitEpoll();
        // 3.添加listen进epoll
        _epoller->AddEvent(_listensock->GetSockfd(), EPOLLIN);
    }

    void Loop()
    {
        _stop = false;
        while (!_stop)
        {
            _epoller->DebugFdList();
            // 默认设为阻塞,为了方便实验
            int timeout = 3000;
            int n = _epoller->EpollWait(_revent, gmaxnum, timeout);
            switch (n)
            {
            case 0:
                ILOG("当前未就绪...,lasttime:%d", timeout);
                break;
            case -1:
                DLOG("等待出错...lasttime:%d", timeout);
                break;
            default:
                ILOG("当前有事件就绪!就绪的个数是%d", n);
                HandlerEvent(n);
            }
        }
        _stop = true;
    }
    ~EpollServer()
    {
        _stop = true;
    }

private:
    // 遍历revent 获取文件描述符和事件
    void HandlerEvent(int n)
    {
        for (int i = 0; i < n; i++)
        {
            uint32_t event = _revent[i].events;
            int sockfd = _revent[i].data.fd;
            // 目前只处理读事件
            if (event & EPOLLIN)
            {
                // 读事件分为 1.连接事件 2.read事件
                if (sockfd == _listensock->GetSockfd())
                {
                    uint16_t peerport;
                    std::string peerip;
                    if (!Accepter(&peerip, &peerport))
                        continue;
                    ILOG("获取一个新连接,%s:%d", peerip.c_str(), peerport);
                }
                else{
                    //处理读取问题
                    char buffer[1024];
                    int n=recv(sockfd,buffer,sizeof(buffer)-1,0);
                    if(n>0){
                        //正常读
                        buffer[n]=0;
                        std::cout<<"client say#"<<buffer;
                        std::string message="你好client,我是server:";
                        message+=buffer;
                        send(sockfd,message.c_str(),message.size(),0);
                    }
                    //处理异常和读取失败
                    else{
                        if(n==0)
                            ILOG("client exit!");
                        if(n==-1)
                            ELOG("read error!!!,%d:%s",errno,strerror(errno));
                        //先取消epoll,再关闭fd
                        _epoller->DeletEvent(sockfd);
                        close(sockfd);
                    }

                }
            }
        }
    }

    bool Accepter(std::string *peerip, uint16_t *peerport)
    {
        Socket *sock = _listensock->AcceptConnection(peerip, peerport);
        if (!sock)
        {
            delete sock;
            return false;
        }
        int sockfd = sock->GetSockfd();
        // 添加到epoll中
        _epoller->AddEvent(sockfd, EPOLLIN);
        delete sock;
        return true;
    }

private:
    int _serverport;
    bool _stop;
    struct epoll_event _revent[gmaxnum];
    std::unique_ptr<Epoller> _epoller;
    std::unique_ptr<Socket> _listensock;
};